package cn.xinfei.xdecision.common.service.rpc;

import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;

import java.util.LinkedHashMap;

public class RpcContext extends LinkedHashMap<String, Object> {
    public static final String REQUEST_ATTRIBUTE = RpcContext.class.getName();
    private static final ThreadLocal<RpcContext> threadLocal = new ThreadLocal<>();

    public String getString(String key) {
        Object value = get(key);
        if (value == null) {
            return null;
        }
        return value.toString();
    }

    public String getStringOrDefault(String key, String defaultValue) {
        String value = getString(key);
        if (value == null) {
            return defaultValue;
        }
        return value;
    }

    public Boolean getBoolean(String key) {
        Object value = get(key);
        if (value == null) {
            return null;
        }
        return Boolean.valueOf(value.toString());
    }

    public Boolean getBooleanOrDefault(String key, Boolean defaultValue) {
        Boolean value = getBoolean(key);
        if (value == null) {
            return defaultValue;
        }
        return value;
    }

    public Integer getInteger(String key) {
        Object value = get(key);
        if (value == null) {
            return null;
        }
        return Integer.valueOf(value.toString());
    }

    public Integer getIntegerOrDefault(String key, Integer defaultValue) {
        Integer value = getInteger(key);
        if (value == null) {
            return defaultValue;
        }
        return value;
    }

    public Long getLong(String key) {
        Object value = get(key);
        if (value == null) {
            return null;
        }
        return Long.valueOf(value.toString());
    }

    public Long getLongOrDefault(String key, Long defaultValue) {
        Long value = getLong(key);
        if (value == null) {
            return defaultValue;
        }
        return value;
    }

    public Double getDouble(String key) {
        Object value = get(key);
        if (value == null) {
            return null;
        }
        return Double.valueOf(value.toString());
    }

    public Double getDoubleOrDefault(String key, Double defaultValue) {
        Double value = getDouble(key);
        if (value == null) {
            return defaultValue;
        }
        return value;
    }

    public static String getCurrentString(String key) {
        Object value = getCurrentAttribute(key);
        if (value == null) {
            return null;
        }
        return value.toString();
    }

    public static String getCurrentStringOrDefault(String key, String defaultValue) {
        String value = getCurrentString(key);
        if (value == null) {
            return defaultValue;
        }
        return value;
    }

    public static Boolean getCurrentBoolean(String key) {
        Object value = getCurrentAttribute(key);
        if (value == null) {
            return null;
        }
        return Boolean.valueOf(value.toString());
    }

    public static Boolean getCurrentBooleanOrDefault(String key, Boolean defaultValue) {
        Boolean value = getCurrentBoolean(key);
        if (value == null) {
            return defaultValue;
        }
        return value;
    }

    public static Integer getCurrentInteger(String key) {
        Object value = getCurrentAttribute(key);
        if (value == null) {
            return null;
        }
        return Integer.valueOf(value.toString());
    }

    public static Integer getCurrentIntegerOrDefault(String key, Integer defaultValue) {
        Integer value = getCurrentInteger(key);
        if (value == null) {
            return defaultValue;
        }
        return value;
    }

    public static Long getCurrentLong(String key) {
        Object value = getCurrentAttribute(key);
        if (value == null) {
            return null;
        }
        return Long.valueOf(value.toString());
    }

    public static Long getCurrentLongOrDefault(String key, Long defaultValue) {
        Long value = getCurrentLong(key);
        if (value == null) {
            return defaultValue;
        }
        return value;
    }

    public static Double getCurrentDouble(String key) {
        Object value = getCurrentAttribute(key);
        if (value == null) {
            return null;
        }
        return Double.valueOf(value.toString());
    }

    public static Double getCurrentDoubleOrDefault(String key, Double defaultValue) {
        Double value = getCurrentDouble(key);
        if (value == null) {
            return defaultValue;
        }
        return value;
    }

    public static Object getCurrentAttribute(String key) {
        RpcContext currentContext = getCurrentContext();
        if (currentContext == null) {
            return null;
        }
        return currentContext.get(key);
    }

    public static Object putCurrentAttribute(String key, Object value) {
        RpcContext currentContext = getCurrentContext();
        if (currentContext == null) {
            currentContext = new RpcContext();
            setCurrentContext(currentContext);
        }
        return currentContext.put(key, value);
    }

    public static Object removeCurrentAttribute(String key) {
        RpcContext currentContext = getCurrentContext();
        if (currentContext == null) {
            return null;
        }
        return currentContext.remove(key);
    }

    public static void setCurrentContext(RpcContext rpcContext) {
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        if (requestAttributes == null) {
            threadLocal.set(rpcContext);
            return;
        }
        requestAttributes.setAttribute(REQUEST_ATTRIBUTE, rpcContext, RequestAttributes.SCOPE_REQUEST);
    }

    public static RpcContext getCurrentContext() {
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        if (requestAttributes == null) {
            return threadLocal.get();
        }
        return (RpcContext)requestAttributes.getAttribute(REQUEST_ATTRIBUTE, RequestAttributes.SCOPE_REQUEST);
    }

    public static void removeCurrentContext() {
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        if (requestAttributes == null) {
            threadLocal.remove();
        } else {
            requestAttributes.removeAttribute(REQUEST_ATTRIBUTE, RequestAttributes.SCOPE_REQUEST);
        }
    }
}